package com.pine.app.module.security.core.authorize.decisions;

import com.pine.app.module.security.core.Authentication;
import com.pine.app.module.security.core.SecurityContextHolder;
import com.pine.app.module.security.core.authorize.manager.MethodAuthorizeDataManager;
import com.pine.app.module.security.core.authorize.metadataSource.ConfigAttribute;
import com.pine.app.module.security.core.authorize.metadataSource.PermissionType;
import com.pine.app.module.security.core.common.enums.ErrorType;
import com.pine.app.module.security.oauth.exception.AuthenticationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Set;

/**
 * @author xiaoyuan
 * @create 2020/3/23 16:15
 **/
public class PermsAuthorizeDecision implements AuthorizeDecision {


    private MethodAuthorizeDataManager methodAuthorizeDataManager;


    @Autowired
    public void setSecurityMetadataSource(MethodAuthorizeDataManager methodAuthorizeDataManager) {
        this.methodAuthorizeDataManager = methodAuthorizeDataManager;
    }

    @Override
    public boolean decide(List<ConfigAttribute> list, HttpServletRequest request, String... target) {
        Authentication authentication =  SecurityContextHolder.getContext().getAuthentication();
        if (authentication == null) {
            ErrorType.AUTHENTICATION_ERROR.throwThis(AuthenticationException::new);
        }
        AntPathMatcher antPathMatcher = new AntPathMatcher();
        return permsDecision(list, methodAuthorizeDataManager.getResources(), antPathMatcher);
    }

    @Override
    public String getType() {
        return PermissionType.PERMS.getCode();
    }

    public boolean permsDecision(List<ConfigAttribute> list, Set<String> resource, AntPathMatcher antPathMatcher) {
        if (!CollectionUtils.isEmpty(list) && CollectionUtils.isEmpty(resource)) {
            return false;
        }
        final boolean[] result = {false};
        list.forEach(configAttribute -> {
            resource.forEach(r -> {
                if (antPathMatcher.match(configAttribute.getCode(), "perms(" + r + ")")) {
                    result[0] = true;
                }
            });
        });
        return result[0];
    }
}
